package com.google.memoryofaplace;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.ResourceBundle;
import java.util.TreeSet;

import javax.servlet.http.HttpServletRequest;

import org.owasp.validator.html.AntiSamy;
import org.owasp.validator.html.CleanResults;
import org.owasp.validator.html.Policy;
import org.owasp.validator.html.PolicyException;
import org.owasp.validator.html.ScanException;

import com.beoui.geocell.GeocellUtils;
import com.beoui.geocell.model.Point;
import com.google.appengine.repackaged.org.json.JSONException;
import com.google.appengine.repackaged.org.json.JSONObject;

public class General {
	public static final String OK = "OK";
	public static final String KO = "KO";

	public static final int MAX_QUERY_ROWS_CAROUSEL = 20;
	public static final int MAX_QUERY_ROWS_PLACE_MEDIA = 6;
	public static final int MAX_QUERY_ROWS_PLACE_COMMENTS = 4;
	public static final int MAX_QUERY_ROWS_PLACES_NEAR = 6;
	
	public static final int MAX_DISTANCE_FROM_CENTER = 20000; //20 km

	public static String[] RPC_ACTIONS = { "addPlace", "addPlaceMedia",
			"addPlaceComment", "denounce", "getPlaces", "getPlaceMedia","getPlaceMediaList",
			"getPlaceComments","getLastPlaces", "getLastPlacesMedia", "getPlace", "upload" };

	public static String[] ADM_ACTIONS = { "addAdminUser", "getAdminUsers",
			"getDenounces","getPlace", "getPlaces", "getPlaceMedia", "getPlaceComments",
			"getLastPlacesMedia","updatePlace"};

	public static Locale currentLocale = Locale.getDefault();

	public static final List<String> IMAGE_TYPES = Arrays.asList("image/png",
			"image/jpeg", "image/tiff", "image/gif", "image/bmp");

	public static boolean isImage(String contentType) {
		return IMAGE_TYPES.contains(contentType);
	}

	public static String getLocaleMessage(String strKey) {
		ResourceBundle labels = ResourceBundle.getBundle("messages",
				currentLocale);
		return labels.getString(strKey);
	}

	public static String validateParams(HttpServletRequest req, String[] actions) {
		String strError = "";

		if (req.getParameter("action") == null)
			strError = returnError(General.getLocaleMessage("invalidParams"))
					.toString();
		else {

			String strAction = req.getParameter("action");
			Arrays.sort(actions);
			if (Arrays.binarySearch(actions, strAction) < 0)
				strError = returnError(
						General.getLocaleMessage("invalidParams")).toString();
		}
		return strError;
	}

	public static JSONObject returnError(String strError) {
		JSONObject responseJSON = new JSONObject();
		try {
			responseJSON.put("desc", strError);
			responseJSON.put("date", General.formatDate(new Date()));
			responseJSON.put("status", KO);
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return responseJSON;

	}

	public static JSONObject returnOK() {
		JSONObject responseJSON = new JSONObject();
		try {
			responseJSON.put("status", OK);
			responseJSON.put("date", General.formatDate(new Date()));
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return responseJSON;

	}

	public static String formatDate(Date dt) {
		if (dt == null)
			return "";
		else {
			DateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm");
			return df.format(dt);
		}
	}

	public static String formatDate(Date dt, String strFormat) {
		if (dt == null)
			return "";
		else {
			DateFormat df = new SimpleDateFormat(strFormat);
			return df.format(dt);
		}
	}

	@SuppressWarnings("deprecation")
	public static String sanitize(String string) {
		CleanResults results = null;
		String strReturn = "";
		if (string == null)
			strReturn = "";
		else {
			try {
				AntiSamy sanitizer = new AntiSamy();
				Policy policy;
				policy = Policy
						.getInstance(General.class
								.getResourceAsStream("/com/google/memoryofaplace/antisamy.xml"));
				sanitizer.setPolicy(policy);

				results = sanitizer.scan(string);
			} catch (ScanException e) {
				e.printStackTrace();
			} catch (PolicyException e) {
				e.printStackTrace();
			}
		}
		if (results != null) {
			strReturn = results.getCleanHTML();
		}

		return strReturn;
	}

	public static boolean isNumber(String number) {
		try {
			@SuppressWarnings("unused")
			Double d = Double.parseDouble(number);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public static int randomInt(int min, int max) {
		Random rand = new Random();
		return rand.nextInt(max - min + 1) + min;
	}

	public static HashMap<Long, Long> sortHashMap(HashMap<Long, Long> input,
			Boolean ascending) {
		Map<Long, Long> tempMap = new HashMap<Long, Long>();
		for (Long wsState : input.keySet()) {
			tempMap.put(wsState, input.get(wsState));
		}

		List<Long> mapKeys = new ArrayList<Long>(tempMap.keySet());
		List<Long> mapValues = new ArrayList<Long>(tempMap.values());
		HashMap<Long, Long> sortedMap = new LinkedHashMap<Long, Long>();
		TreeSet<Long> sortedSet = new TreeSet<Long>(mapValues);
		Object[] sortedArray = sortedSet.toArray();
		int size = sortedArray.length;
		if (ascending) {
			for (int i = 0; i < size; i++) {
				sortedMap.put(mapKeys.get(mapValues.indexOf(sortedArray[i])),
						(Long) sortedArray[i]);
			}
		} else {
			for (int i = size - 1; i >= 0; i--) {
				sortedMap.put(mapKeys.get(mapValues.indexOf(sortedArray[i])),
						(Long) sortedArray[i]);
			}
		}
		return sortedMap;
	}

	public static HashMap<String, Long> sortHashMapString(
			HashMap<String, Long> input, Boolean ascending) {
		Map<String, Long> tempMap = new HashMap<String, Long>();
		for (String wsState : input.keySet()) {
			tempMap.put(wsState, input.get(wsState));
		}

		List<String> mapKeys = new ArrayList<String>(tempMap.keySet());
		List<Long> mapValues = new ArrayList<Long>(tempMap.values());
		HashMap<String, Long> sortedMap = new LinkedHashMap<String, Long>();
		TreeSet<Long> sortedSet = new TreeSet<Long>(mapValues);
		Object[] sortedArray = sortedSet.toArray();
		int size = sortedArray.length;
		if (ascending) {
			for (int i = 0; i < size; i++) {
				sortedMap.put(mapKeys.get(mapValues.indexOf(sortedArray[i])),
						(Long) sortedArray[i]);
			}
		} else {
			for (int i = size - 1; i >= 0; i--) {
				sortedMap.put(mapKeys.get(mapValues.indexOf(sortedArray[i])),
						(Long) sortedArray[i]);
			}
		}
		return sortedMap;
	}

	public static double distanceFromCenterArea(Double latitude, Double longitude)
	{
		Point p1 = new Point(42.347507, 13.404007);    // L'Aquila
		Point p2 = new Point(latitude, longitude); 
		return GeocellUtils.distance(p1, p2);
	}
	
	public static String returnString(String string)
	{
		if (string.isEmpty()||string==null)
			return "-";
		
		return string;
	}
	
}

